package com.bilibili.juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABAProblemDemo {

    static AtomicInteger atomicInteger = new AtomicInteger(100) ;
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<Integer>(100,1);

    public static void main(String[] args) {

        //abahappen();
        stampedhappen();

    }

    private static void stampedhappen() {
        new Thread(() -> {

            int stampe = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t"+"首次版本号："+stampe);
            try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }

            atomicStampedReference.compareAndSet(100,101,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t"+"2次版本号："+atomicStampedReference.getStamp());

            try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }

            atomicStampedReference.compareAndSet(101,100,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t"+"3次版本号："+atomicStampedReference.getStamp());


        },"t3").start();


        new Thread(() -> {

            int stampe = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t"+"首次版本号："+stampe);

            //等待现场3发生ABA
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }

           // boolean b = atomicStampedReference.compareAndSet(100,2022,
                    //atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);

           boolean b = atomicStampedReference.compareAndSet(100,2022,stampe
            ,stampe+1);

            System.out.println(b+"\t"+Thread.currentThread().getName()+"\t"
                    +atomicStampedReference.getReference()+"\t"+ atomicStampedReference.getStamp());


        },"t4").start();





    }

    private static void abahappen() {
        new Thread(() -> {
            atomicInteger.compareAndSet(100,101);
            try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }
            atomicInteger.compareAndSet(101,100);
        },"t1").start();

        new Thread(() -> {
            try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(atomicInteger.compareAndSet(100, 2022)+"\t"+atomicInteger.get());
        },"t2").start();
    }
}
